#region Copyright

// The contents of this file are subject to the Mozilla Public License
//  Version 1.1 (the "License"); you may not use this file except in compliance
//  with the License. You may obtain a copy of the License at
//  
//  http://www.mozilla.org/MPL/
//  
//  Software distributed under the License is distributed on an "AS IS"
//  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
//  License for the specific language governing rights and limitations under 
//  the License.
//  
//  The Initial Developer of the Original Code is Robert Smyth.
//  Portions created by Robert Smyth are Copyright (C) 2008.
//  
//  All Rights Reserved.

#endregion

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using NUnit.Extensions.NUnitGridRunner.Metrics;
using NUnitGridThreadRunner.Alchemi.Metrics;


namespace NUnit.Extensions.NUnitGridRunner.NUnit
{
    public class TestResultsParser : ITestResultsParser
    {
        private readonly StringBuilder message = new StringBuilder();
        private readonly string testResultsXml;
        private bool valid;

        public TestResultsParser(string testResultsXml)
        {
            this.testResultsXml = testResultsXml;
        }

        public bool Valid
        {
            get { return valid; }
        }

        public FixtureMetricsCollection Parse()
        {
            FixtureMetrics[] fixtureMetrics;
            var document = new XmlDocument();
            try
            {
                document.LoadXml(testResultsXml);

                fixtureMetrics = ReadFixtures(document);

                valid = true;
            }
            catch (Exception exception)
            {
                fixtureMetrics = new FixtureMetrics[0];
                valid = false;
                message.AppendFormat("\nUnable to read XML.\nException: {0}\n", exception.Message);
            }

            return new FixtureMetricsCollection(fixtureMetrics);
        }

        public string Message
        {
            get { return message.ToString(); }
        }

        private static FixtureMetrics[] ReadFixtures(XmlNode document)
        {
            var fixtures = new List<FixtureMetrics>();
            XmlNodeList nodeList = document.SelectNodes("/test-results/test-suite//test-suite/results/test-case/../..");
            foreach (XmlNode node in nodeList)
            {
                string fixtureName = GetFixtureName(node);

                float timeInSeconds = float.Parse(node.Attributes["time"].Value);

                fixtures.Add(
                    new FixtureMetrics(Environment.MachineName, fixtureName, TimeSpan.FromSeconds(timeInSeconds)));
            }
            return fixtures.ToArray();
        }

        private static string GetFixtureName(XmlNode node)
        {
            var nameNodes = new List<string>();
            nameNodes.Add(node.Attributes["name"].Value);
            XmlNode parentNode = node.ParentNode;
            while (parentNode != null)
            {
                if (parentNode.Name == "test-suite")
                {
                    nameNodes.Add(parentNode.Attributes["name"].Value);
                }
                parentNode = parentNode.ParentNode;
            }
            nameNodes.Reverse();
            nameNodes.RemoveAt(0);
            return string.Join(".", nameNodes.ToArray());
        }

        private static TimeSpan ReadTotalRunTime(XmlNode document)
        {
            XmlNode suiteNode = document.SelectSingleNode("/test-results/test-suite");
            float suiteTotalTimeInSeconds = float.Parse(suiteNode.Attributes["time"].Value);
            return TimeSpan.FromSeconds(suiteTotalTimeInSeconds);
        }
    }
}